package handlers

import (
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"gitee.com/dreamwithouttrace/websocket-module/core"
	"gitee.com/dreamwithouttrace/websocket-module/transport"

	"github.com/gorilla/websocket"
)

// HandshakeHandler WebSocket握手处理器
type HandshakeHandler struct {
	transport *transport.Transport
	config    *core.Config
	redis     interface{} // Redis客户端接口，需要根据具体实现调整
}

// NewHandshakeHandler 创建新的握手处理器
func NewHandshakeHandler(transport *transport.Transport, config *core.Config, redis interface{}) *HandshakeHandler {
	return &HandshakeHandler{
		transport: transport,
		config:    config,
		redis:     redis,
	}
}

// Handshake 处理WebSocket握手
func (h *HandshakeHandler) Handshake(user core.User, ip string, w http.ResponseWriter, r *http.Request) error {
	// 生成频道ID
	channelID := h.generateChannelID()

	// 创建WebSocket连接
	conn := core.NewWebSocketConnection(
		user,
		channelID,
		user.GetUniqueID(),
		ip,
		nil, // 连接将在升级后设置
		h.transport.GetWaitGroup(),
	)

	user.SetLastInnerIP(ip)
	user.SetLastLoginTime(time.Now().Unix())

	// 检查连接限制
	if !h.checkConnectionLimit(user) {
		return &ConnectionLimitError{Message: "连接数超限"}
	}

	// 踢出已存在的连接
	h.kickExistingConnection(user)

	// 设置Redis缓存
	h.setRedisCache(user, channelID)

	// 创建WebSocket升级器
	upgrader := &websocket.Upgrader{
		ReadBufferSize:    h.config.ReadBufferSize,
		WriteBufferSize:   h.config.WriteBufferSize,
		EnableCompression: h.config.EnableCompression,
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	// 处理协议
	protocol := r.Header.Get("Sec-WebSocket-Protocol")
	var wsConn *websocket.Conn
	var err error

	if protocol != "" {
		headers := h.createProtocolHeaders(protocol, strconv.FormatInt(user.GetAppID(), 10))
		wsConn, err = upgrader.Upgrade(w, r, headers)
	} else {
		wsConn, err = upgrader.Upgrade(w, r, nil)
	}

	if err != nil {
		log.Println("client upgrade error:", err)
		return err
	}

	// 设置连接
	conn.SetWebSocketConn(wsConn)

	// 添加到传输管理器
	h.transport.AddSocketClient(conn)

	return nil
}

// generateChannelID 生成频道ID
func (h *HandshakeHandler) generateChannelID() string {
	// 这里可以根据需要实现更复杂的ID生成逻辑
	return strconv.FormatInt(time.Now().UnixNano(), 10)
}

// checkConnectionLimit 检查连接限制
func (h *HandshakeHandler) checkConnectionLimit(user core.User) bool {
	// 这里需要根据具体的Redis实现来检查连接限制
	// 示例实现：
	// key := "connect:" + user.GetUniqueID()
	// exists, err := h.redis.Exists(key).Result()
	// if err != nil {
	//     return false
	// }
	// if exists == 1 {
	//     return false
	// }
	// h.redis.SetNX(key, 1, time.Minute)
	return true
}

// kickExistingConnection 踢出已存在的连接
func (h *HandshakeHandler) kickExistingConnection(user core.User) {
	// 检查用户是否已在线
	//log.Println("kick existing connection", user.GetID(), h.transport.Exists(user.GetID()))
	if h.transport.Exists(user.GetID()) {
		h.transport.Kick(user.GetID(), user.GetSocketID())
	}
}

// setRedisCache 设置Redis缓存
func (h *HandshakeHandler) setRedisCache(user core.User, channelID string) {
	// 这里需要根据具体的Redis实现来设置缓存
	// 示例实现：
	// key := "sock:" + user.GetUniqueID()
	// h.redis.Set(key, channelID, time.Second*180)
}

// createProtocolHeaders 创建协议头
func (h *HandshakeHandler) createProtocolHeaders(protocol string, appID string) map[string][]string {
	var headers = make(map[string][]string)
	var node = []string{"chat-client-" + appID}

	if strings.Contains(protocol, ",") {
		array := strings.Split(protocol, ",")
		if !h.containsString(array, node[0]) {
			return headers
		}
	}

	headers["Sec-WebSocket-Protocol"] = node
	return headers
}

// containsString 检查字符串数组中是否包含指定字符串
func (h *HandshakeHandler) containsString(array []string, target string) bool {
	for _, item := range array {
		if item == target {
			return true
		}
	}
	return false
}

// ConnectionLimitError 连接限制错误
type ConnectionLimitError struct {
	Message string
}

func (e *ConnectionLimitError) Error() string {
	return e.Message
}

// WebSocketConnection 扩展WebSocket连接以支持设置连接
type WebSocketConnection interface {
	core.Connection
	SetWebSocketConn(conn *websocket.Conn)
}
